/**
 * v0.0.1
 */
type StateEvent = { connect: boolean }
export class WebSocketPlus {
  private ws: WebSocket
  private readonly url: string
  // 自动重连
  private autoRecon = true
  // 设备为关闭状态，为true时不再自动重连
  private isClose = false
  public isConnected = false
  constructor (url: string, options?: { autoRecon?: boolean }) {
    this.url = url
    if (options && options.autoRecon) {
      this.autoRecon = options.autoRecon
    }
    this.open()
  }

  private openId = 0
  open () {
    this.openId += 1
    // 如果存在先关闭
    if (this.ws) this.close()
    this.isClose = false
    this.ws = new WebSocket(this.url)
    this.ws.onopen = (ev) => {
      this.isConnected = true
      this._onOpen && this._onOpen(ev)
      this.updateState()
    }
    this.ws.onmessage = (ev) => {
      this._onMessage && this._onMessage(ev)
    }
    this.ws.onclose = (ev) => {
      this.isConnected = false
      this.updateState()
      this.reconnect()
      this._onClose && this._onClose(ev)
    }
  }

  close () {
    this.isClose = true
    if (this.ws) this.ws.close()
    this.ws = null
  }

  private _onOpen: { (ev: Event) }
  onOpen (callback: { (ev: Event) }) {
    this._onOpen = callback
    return this
  }

  private _onMessage: { (ev: MessageEvent) }
  onMessage (callback: { (ev: MessageEvent) }) {
    this._onMessage = callback
    return this
  }

  private _onClose: { (ev: CloseEvent) }
  onClose (callback: { (ev: Event) }) {
    this._onClose = callback
    return this
  }

  private _onState: { (ev: StateEvent) }
  onState (callback: { (ev: StateEvent) }) {
    this._onState = callback
    return this
  }

  private updateState () {
    if (this._onState) {
      this._onState({
        connect: this.isConnected
      })
    }
  }

  private reconnect () {
    if (!this.isClose) {
      const _openId = this.openId
      setTimeout(() => {
        if (!this.isClose && _openId === this.openId) this.open()
      }, 3000)
    }
  }
}
